package pong.game.open_gl;

import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import pong.game.data.Data;
import pong.mathematic.Engine;
import pong.mathematic.Vector3D;
import android.content.Context;
import android.graphics.Bitmap;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.util.Log;

public class Renderer implements android.opengl.GLSurfaceView.Renderer {

	private static final String TAG = "Renderer";

	private static final int SLEEP_TIME = 100;

	// private static int SLEEP_TIME = 100;
	// private static boolean sleepRender = false;

	private MyGLSurfaceView parentSurface = null;

	private boolean isSleep = false;

	private Context context = null;
	private static int width = 1;
	private static int height = 1;

	public Renderer(Context context) {
		this.context = context;
	}

	public static Bitmap savePixelsALL(GL10 gl) {
		return savePixels(0, 0, width, height, gl);
	}

	public static Bitmap savePixels(int x, int y, int w, int h, GL10 gl) {
		int b[] = new int[w * h];
		int bt[] = new int[w * h];
		IntBuffer ib = IntBuffer.wrap(b);
		ib.position(0);
		gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);

		/*
		 * remember, that OpenGL bitmap is incompatible with Android bitmap and
		 * so, some correction need.
		 */
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				int pix = b[i * w + j];
				int pb = (pix >> 16) & 0xff;
				int pr = (pix << 16) & 0x00ff0000;
				int pix1 = (pix & 0xff00ff00) | pr | pb;
				bt[(h - i - 1) * w + j] = pix1;
			}
		}
		return Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_4444);
	}

	public void onDrawFrame(GL10 gl) {

		if (!isSleeping()) {

			Engine.getInstance().run();

			gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

			gl.glPushMatrix();
			// Get Camera Position;
			Vector3D camPos = Data.getInstance().getCamera().getPosition();

			// Log.i(TAG, "campos = " + camPos.toString());
			GLU.gluLookAt(gl, camPos.getX(), camPos.getY(), camPos.getZ(), camPos.getX(), camPos.getY(),
					camPos.getZ() - 1, 0, 1, 0);

			camPos = null;

			Data.getInstance().render(gl);

			gl.glPopMatrix();

			// RENDER !!!
			parentSurface.requestRender();

			// Log.v(TAG, "Render");
		} else {
			try {
				Thread.sleep(SLEEP_TIME);
				// Log.v(TAG, "Sleep");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	public void onSurfaceChanged(GL10 gl, int width, int height) {

		Renderer.width = width;
		Renderer.height = height;

		Data.getInstance().initSize(height, width);
		// Sets the current view port to the new size.
		gl.glViewport(0, 0, width, height);

		// Select the projection matrix
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		float ratio = (float) width / height;
		if (ratio < 1) {
			GLU.gluPerspective(gl, 45.0f, ratio, 0.001f, 100000f);
		} else {
			GLU.gluPerspective(gl, 45.0f / ratio, ratio, 0.001f, 100000f);
		}
		Engine.getInstance().setViewRatio(ratio);
		Engine.getInstance().setScreenSize(width, height);

		gl.glMatrixMode(GL10.GL_MODELVIEW);
		// Reset the modelview matrix
		gl.glLoadIdentity();
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config) {

		Log.i(TAG, "Surface create");

		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glClearColor(0, 0, 0, 1f);
		// gl.glClearColor(1.0f, 1.0f, 1.0f, 1f);
		// gl.glShadeModel(GL10.GL_SMOOTH);
		gl.glEnable(GL10.GL_BLEND);
		gl.glFrontFace(GL10.GL_CCW);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

		// BAIZOR updates
		gl.glDisable(GL10.GL_NORMALIZE);
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
		// gl.glPolygonMode(GL10.GL_LINE_STRIP );
		parentSurface.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
		// end BAIZOR updates

		// Data.getInstance().setContext(context);

		Log.d(TAG, "GLSurface Render is created \"memory\"");
	}

	public void setSleep(boolean state) {

		this.isSleep = state;

		if (state) {

			// Data.getInstance().setBubblesGeneratorSleep(state);
			// Data.getInstance().suspendBitmapQueue(false);

		} else {
			// Data.getInstance().setBubblesGeneratorSleep(state);
			// Data.getInstance().resumeBitmapQueue();
			Engine.getInstance().updateTime();
			parentSurface.requestRender();
		}
	}

	public void setParentSurface(MyGLSurfaceView parent) {
		parentSurface = parent;
	}

	public boolean isSleeping() {
		return isSleep;
	}
}
